/*
    http://bhepple.freeshell.org

    Copyright (C) 2010 Bob Hepple <bhepple@freeshell.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/

/**
 * \file tbm_test.c unit tests for tbm.c

 * To run from the source directory:
 *
 * libtool --mode=execute valgrind --leak-check=full ./tests/tbm_test
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tbs.h>
#include <tba.h>
#include <tbm.h>
#include "./tb_expect.h"

void *xcalloc (size_t nmemb, size_t size)
{
    void *retval = calloc(nmemb, size);

    /* Normally (ie as specified on GNU pages), xcalloc etc do not
     * return when the heap is exhausted. tba does not make that
     * assumption and provides code for the heap exhaustion case.
     *
     * For example, a longjmp could be used here to take us to a
     * recovery routine ie a routine that has previously called
     * setjmp(). It could free some stuff (maybe a buffer alloc'd as a
     * safety reserve) and then either exit safely or try to continue,
     * perhaps with a warning.
     *
     * extern jmp_buf               NoMoreHeap; 
     * if (!retval) longjmp(NoMoreHeap, 1); */

    return(retval);
}

void *xmalloc (size_t size)
{
    void *retval = malloc(size);
    /* if (!retval) longjmp(NoMoreHeap, 1); */
    return(retval);
}

void *xrealloc(void *oldbuf, size_t size)
{
    void *retval = NULL;

    retval = realloc(oldbuf, size);

    /* if (!retval) longjmp(NoMoreHeap, 1); */
    return(retval);
}

void xfree(void *buf)
{
    free(buf);
}

#define TEST_STRING "Hello world"

void header(char *s, int error)
{
    static int last_error = 0;
    if (error == last_error) {
        printf("ok\n");
    } else {
        last_error = error;
    }

    printf("*******************************\n%s:\n", s);
}

#define PRINT_CLUES

int unittest(int min_maxlen)
{
    tba a = NULL;
    int errors = 0;
    int value;
    tbs result = NULL;
    tbs expected = NULL;
    tbs command = NULL;
    int i;
    int status;

#define new_str(s,x) s=xmalloc(strlen(x));strcpy(s,x) 

    header("tbm_backtick", errors);
    tba_push_str(&a, "/usr/bin/echo");
    tba_push_str(&a, TEST_STRING);
    result = tbm_backtick(a);
    expected = tbs_new(TEST_STRING "\n");
    iEXPECT(tbs_strcmp(result, expected), 0);
    tbs_free(&result);
    tbs_free(&expected);
    for (i = 0; a[i]; i++) xfree(a[i]);
    tba_free(&a);

    header("tbm_backtick", errors);
    tba_push_str(&a, "/usr/bin/echo");
    tba_push_str(&a, "-n" );
    tba_push_str(&a, TEST_STRING);
    result = tbm_backtick(a);
    expected = tbs_new(TEST_STRING);
    iEXPECT(tbs_strcmp(result, expected), 0);
    tbs_free(&result);
    tbs_free(&expected);

    header("tbm_system", errors);
    command = tbs_new("/usr/bin/echo " TEST_STRING);
    status = 0;
    result = tbm_system(command, &status);
    expected = tbs_new(TEST_STRING "\n");
    iEXPECT(tbs_strcmp(result, expected), 0);
    tbs_free(&result);
    tbs_free(&command);
    tbs_free(&expected);

    header("tbm_system(echo " TEST_STRING ")", errors);
    command = tbs_new("echo " TEST_STRING);
    status = 0;
    result = tbm_system(command, &status);
    iEXPECT(status,0);
    expected = tbs_new(TEST_STRING "\n");
    iEXPECT(tbs_strcmp(result, expected), 0);
    tbs_free(&result);
    tbs_free(&command);
    tbs_free(&expected);

    header("tbm_system(echo " TEST_STRING ">&2; exit 2)", errors);
    command = tbs_new("echo \"" TEST_STRING "\" >&2; exit 2");
    status = 0;
    result = tbm_system(command, &status);
    iEXPECT(status,2);
    expected = tbs_new("");
    iEXPECT(tbs_strcmp(result, expected), 0);
    tbs_free(&result);
    tbs_free(&command);
    tbs_free(&expected);
    
    header("tbm_system(false)", errors);
    command = tbs_new("false");
    status = 0;
    result = tbm_system(command, &status);
    iEXPECT(status,1);
    tbs_free(&result);
    tbs_free(&command);
    
end:
    return(errors);
}

int main(int argc, char **argv)
{
    int errors = 0;

    errors += unittest(1);

    printf("%d error%c\n", errors, errors == 1? ' ': 's');
    return(errors);
}

